/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.service.impl;

import com.xy.biz.base.client.GoodsClient;
import com.xy.biz.base.domain.req.GetGoodsRequest;
import com.xy.biz.base.domain.resp.GetGoodsResponse;
import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.domain.resp.GetDocumentResponse;
import com.xy.biz.xd.domain.bo.TechniqueBO;
import com.xy.biz.xd.domain.bo.TechniqueDocumentBO;
import com.xy.biz.xd.domain.query.TechniqueByIdQuery;
import com.xy.biz.xd.domain.query.TechniqueQuery;
import com.xy.biz.xd.manager.TechniqueManager;
import com.xy.biz.xd.service.TechniqueService;
import com.xy.lang.domain.Result;
import com.xy.lang.enums.ApplyStatusEnum;
import com.xy.lang.enums.AuditStatusEnum;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zgy
 * @date 2022-1-11
 */
@Service("techniqueService")
public class TechniqueServiceImpl implements TechniqueService {

    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private TechniqueManager techniqueManager;

    @Override
    public Result<?> saveTechnique(TechniqueBO techniqueBO) {
        GetGoodsResponse goodsResponse = ResultUtils.get(goodsClient.getGoods(
                GetGoodsRequest.builder().goodsId(techniqueBO.getGoodsId()).build()));
        if (Objects.isNull(goodsResponse)) {
            return Result.ofNotFound(String.valueOf(techniqueBO.getGoodsId()));
        }
        Result<Map<Long, GetDocumentResponse>> result = getDocumentMap(techniqueBO);
        if (!result.wasSuccess()) {
            return result;
        }
        Map<Long, GetDocumentResponse> data = result.getData();
        buildTechnique(techniqueBO, goodsResponse, data);
        if (CollectionUtils.isEmpty(techniqueBO.getTechniqueDocumentList())) {
            return Result.ofBadRequest();
        }
        int affectedRows = techniqueManager.saveTechnique(techniqueBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        if (affectedRows == -1) {
            return Result.ofBadRequest("此货号信息已存在启用数据");
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> saveAllTechnique(Collection<TechniqueBO> collection) {
        int affectedRows = techniqueManager.saveAllTechnique(collection);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateTechnique(TechniqueBO techniqueBO) {
        TechniqueBO technique = techniqueManager.getTechnique(TechniqueByIdQuery.builder().techniqueId(techniqueBO.getTechniqueId()).build());
        if (Objects.isNull(technique)) {
            return Result.ofNotFound(String.valueOf(techniqueBO.getTechniqueId()));
        }
        GetGoodsResponse goodsResponse = null;
        if (Objects.nonNull(techniqueBO.getGoodsId())) {
            goodsResponse = ResultUtils.get(goodsClient.getGoods(
                    GetGoodsRequest.builder().goodsId(techniqueBO.getGoodsId()).build()));
        }
        Result<Map<Long, GetDocumentResponse>> result = getDocumentMap(techniqueBO);
        if (!result.wasSuccess()) {
            return result;
        }
        Map<Long, GetDocumentResponse> data = result.getData();
        buildTechnique(techniqueBO, goodsResponse, data);
        int affectedRows = techniqueManager.updateTechnique(techniqueBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofBadRequest("此产品存在已启用的生产工艺！");
    }

    @Override
    public Result<?> copyTechnique(Long techniqueId) {
        TechniqueBO technique = techniqueManager.getTechnique(TechniqueByIdQuery.builder().techniqueId(techniqueId).build());
        if (Objects.isNull(technique)) {
            return Result.ofNotFound(String.valueOf(techniqueId));
        }
        int row = techniqueManager.copyTechnique(technique);
        if (row > 0) {
            return Result.success();
        }
        if (row == -1) {
            return Result.ofBadRequest("当前生产工艺暂无文档！");
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteTechnique(Long techniqueId) {
        TechniqueBO technique = techniqueManager.getTechnique(TechniqueByIdQuery.builder().techniqueId(techniqueId).build());
        if (Objects.isNull(technique)) {
            return Result.ofNotFound(String.valueOf(techniqueId));
        }
        int affectedRows = techniqueManager.deleteTechnique(techniqueId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public TechniqueBO getTechnique(TechniqueByIdQuery query) {
        return techniqueManager.getTechnique(query);
    }

    @Override
    public List<TechniqueBO> listTechniqueById(Collection<Long> collection) {
        return techniqueManager.listTechniqueById(collection);
    }

    @Override
    public List<TechniqueBO> listTechnique(TechniqueQuery query) {
        return techniqueManager.listTechnique(query);
    }

    @Override
    public int countTechnique(TechniqueQuery query) {
        return techniqueManager.countTechnique(query);
    }

    private Result<Map<Long, GetDocumentResponse>> getDocumentMap(TechniqueBO techniqueBO) {
        Set<Long> documentIdSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(techniqueBO.getTechniqueDocumentList())) {
            for (TechniqueDocumentBO techniqueDocumentBO : techniqueBO.getTechniqueDocumentList()) {
                documentIdSet.add(techniqueDocumentBO.getDocumentId());
            }
        }
        List<GetDocumentResponse> getDocumentResponseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(documentIdSet)) {
            getDocumentResponseList = ResultUtils.get(documentClient.listDocumentById(documentIdSet));
        }
        if (!Objects.equals(documentIdSet.size(), getDocumentResponseList.size())) {
            documentIdSet.removeAll(getDocumentResponseList.stream().map(GetDocumentResponse::getDocumentId).collect(Collectors.toSet()));
            return Result.ofNotFound("不存在的文件：" + documentIdSet);
        }
        Map<Long, GetDocumentResponse> documentResponseMap = getDocumentResponseList.stream().collect(Collectors.toMap(GetDocumentResponse::getDocumentId, e -> e));
        return Result.success(documentResponseMap);
    }

    private void buildTechnique(TechniqueBO techniqueBO, GetGoodsResponse goodsResponse, Map<Long, GetDocumentResponse> data) {
        LocalDateTime now = LocalDateTime.now();
        if (Objects.nonNull(goodsResponse)) {
            techniqueBO.setGoodsAbbr(goodsResponse.getGoodsAbbr());
            techniqueBO.setCategory(goodsResponse.getCategory());
            techniqueBO.setGoodsCode(goodsResponse.getGoodsCode());
            techniqueBO.setGoodsFullCode(goodsResponse.getGoodsFullCode());
        }
        if (Objects.isNull(techniqueBO.getStatus())) {
            techniqueBO.setStatus(ApplyStatusEnum.DRAFT.getCode());
        }
        if (Objects.isNull(techniqueBO.getAuditStatus())) {
            techniqueBO.setAuditStatus(AuditStatusEnum.UNDO.getCode());
        }
        techniqueBO.setTenantId(UserContextHolder.getTenantId());
        techniqueBO.setCreateUserId(UserContextHolder.getUserId());
        techniqueBO.setCreateUserName(UserContextHolder.getUserName());
        techniqueBO.setCreateTime(now);
        techniqueBO.setUpdateUserId(UserContextHolder.getUserId());
        techniqueBO.setUpdateUserName(UserContextHolder.getUserName());
        techniqueBO.setUpdateTime(now);
        techniqueBO.setDeleteFlag(false);
        if (!CollectionUtils.isEmpty(techniqueBO.getTechniqueDocumentList())) {
            for (TechniqueDocumentBO techniqueDocumentBO : techniqueBO.getTechniqueDocumentList()) {
                GetDocumentResponse documentResponse = data.get(techniqueDocumentBO.getDocumentId());
                techniqueDocumentBO.setDocumentName(documentResponse.getDocumentName());
                techniqueDocumentBO.setFileLevel(documentResponse.getLevel());
                techniqueDocumentBO.setFileExtension(documentResponse.getFileExtension());
                techniqueDocumentBO.setVersion(documentResponse.getVersion());
                techniqueDocumentBO.setTenantId(UserContextHolder.getTenantId());
            }
        }
    }

}
